//--------------------------------------------------------------------
//     Author:Howe
//     Date: 2021-04-13 21:46:32 
//     Description:对此文件的更改可能会导致不正确的行为，并且如果重新生成代码，这些更改将会丢失。
//--------------------------------------------------------------------
using System;
using System.Threading.Tasks;
using Kylin.Wiki.Core;
using Kylin.Wiki.Services;
using Kylin.Wiki.Model.Entity;
using Kylin.Wiki.IService;
using Kylin.Wiki.Core.Extensions.AutofacManager;
using Kylin.Wiki.Repository;
using Kylin.Wiki.Model.Api;
using Kylin.Wiki.Model.View;
using Kylin.Wiki.Core.Enum;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
using Kylin.Wiki.Model.Dto;
using System.Linq.Expressions;

namespace Kylin.Wiki.Services
{
    /// <summary>
    /// MenuServices
    /// </summary>	
    public class MenuService : Service<Menu>, IMenuService, IDependency
    {

        public IUser_RoleService _user_RoleServices;

        public IRole_MenuService _role_MenuService;


        public MenuService(IUser_RoleService user_RoleService, IRole_MenuService role_MenuService, IUnitOfWork unitOfWork, IRepository<Menu> repository) : base(unitOfWork, repository)
        {
            _user_RoleServices = user_RoleService;
            base.UnitOfWork = unitOfWork;
            base.Repository = repository;
            _role_MenuService = role_MenuService;
        }

        public ApiResult<List<MenuVM>> GetMenus(int userId)
        {
            ApiResult<List<MenuVM>> result = new ApiResult<List<MenuVM>>();
            //查询所有菜单
            var menus = base.Repository.Find(x => x.Status==false&&x.MenuType!="F")
                .Select(x => new MenuVM
                {
                    MenuName = x.MenuName,
                    MenuID = x.MenuID,
                    OrderNum = x.OrderNum,
                    PID = x.PID,
                    MenuType = x.MenuType,
                    Path = x.Path,
                    Meta = JsonConvert.DeserializeObject<MetaVM>(x.Meta)
                })
                .OrderBy(x=>x.OrderNum)
                .OrderBy(x=>x.MenuID);

            if (userId == 1)
            {

                result.Code = HttpStateCode.Success;
                result.Success = true;
                result.Data = ResolveUserMenuTree(menus.ToList());
                return result;
            }


            //查询角色和菜单关系
            var roles_menus = from a in _user_RoleServices.Find(x => 1 == 1)
                              join b in _role_MenuService.Find(x => 1 == 1) on a.RoleID equals b.RoleID
                              join c in menus on b.MenuID equals c.MenuID
                              where a.UserID == userId
                              select new MenuVM()
                              {
                                  MenuName = c.MenuName,
                                  MenuID = c.MenuID,
                                  OrderNum = c.OrderNum,
                                  PID = c.PID,
                                  MenuType = c.MenuType,
                                  Path = c.Path,
                                  Meta = c.Meta
                              };

            result.Code = HttpStateCode.Success;
            result.Success = true;
            result.Data = ResolveUserMenuTree(roles_menus.ToList());
            return result;
        }
        public ApiResult<List<MenuVM>> GetList()
        {
            ApiResult<List<MenuVM>> result = new ApiResult<List<MenuVM>>();
            //查询所有菜单
            var menus = base.Repository.Find(x => 1 == 1)
                .Select(x => new MenuVM
                {
                    MenuName = x.MenuName,
                    MenuID = x.MenuID,
                    OrderNum = x.OrderNum,
                    PID = x.PID,
                    MenuType = x.MenuType,
                    Path = x.Path,
                    Meta = JsonConvert.DeserializeObject<MetaVM>(x.Meta)
                });
            result.Code = HttpStateCode.Success;
            result.Success = true;
            result.Data = ResolveUserMenuTree(menus.ToList());
            return result;
        }

        public ApiResult<List<MenuVM>> GetListByRoleID(int roleId)
        {
            ApiResult<List<MenuVM>> result = new ApiResult<List<MenuVM>>();
            var roleMenus = _role_MenuService.Find(x => x.RoleID == roleId);
            var menus = from a in roleMenus
                        join b in base.Find(x => 1 == 1) on a.MenuID equals b.MenuID
                        select new MenuVM()
                        {
                            MenuName = b.MenuName,
                            MenuID = b.MenuID,
                            OrderNum = b.OrderNum,
                            PID = b.PID,
                            MenuType = b.MenuType,
                            Path = b.Path,
                            Meta = JsonConvert.DeserializeObject<MetaVM>(b.Meta)
                        };
            result.Code = HttpStateCode.Success;
            result.Success = true;
            result.Data = ResolveUserMenuTree(menus.ToList());
            return result;
        }


        public ApiPageResult<List<MenuVM>> GetListByPage(MenuDTO menuDTO)
        {
            ApiPageResult<List<MenuVM>> result = new ApiPageResult<List<MenuVM>>();
            var orderBy = new Dictionary<string, QueryOrderBy>() { {
                    "OrderNum", QueryOrderBy.Asc
             } };
            var data = base.QueryablePage(menuDTO.PageIndex,
               menuDTO.PageSize,
               out int rowCount,
               x => x.Status == false,
               orderBy).Select(x => new MenuVM
               {
                   MenuName = x.MenuName,
                   MenuID = x.MenuID,
                   OrderNum = x.OrderNum,
                   PID = x.PID,
                   MenuType = x.MenuType,
                   Path = x.Path,
                   Meta = JsonConvert.DeserializeObject<MetaVM>(x.Meta)
               });
            result.Data = ResolveUserMenuTree(data.ToList());
            result.TotalCount = rowCount;
            result.PageIndex = menuDTO.PageIndex;
            result.PageSize = menuDTO.PageSize;
            result.TotalPages = (rowCount % menuDTO.PageSize) > 0 ? rowCount / menuDTO.PageSize + 1 : rowCount / menuDTO.PageSize;
            return result;
        }


        public ApiResult<bool> Create(Menu menu)
        {
            return new ApiResult<bool>(base.Add(menu, true) > 0, HttpStateCode.Success, "添加成功");
        }

        public ApiResult<bool> Update(Menu menu)
        {
            //判断是否存在部门
            if (!base.Exists(x => x.MenuID == menu.MenuID))
                return new ApiResult<bool>(false, HttpStateCode.Error, "该部门不存在");
            Expression<Func<Menu, object>>[] updatedProperties =
            {
                   p=>p.MenuName,
                   p=>p.MenuType,
                   p=>p.Meta,
                   p=>p.Path,   
                   p=>p.PID,
                   p=>p.OrderNum,
                   p=>p.UpdateBy,
                   p=>p.UpdateOn
            };
            int result = base.Update(menu, updatedProperties, true);
            return new ApiResult<bool>(result > 0, HttpStateCode.Success, "修改成功");
        }

        public ApiResult<bool> Delete(Menu menu)
        {
            return new ApiResult<bool>(false, HttpStateCode.Error, "禁止删除");
        }
        /// <summary>
        /// 生成系统菜单树
        /// </summary>
        /// <param name="menus"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private List<MenuVM> ResolveUserMenuTree(List<MenuVM> menus, int parentId = 0)
        {
            List<MenuVM> userMenus = new List<MenuVM>();

            foreach (var menu in menus.Where(m => m.PID == parentId).OrderBy(m => m.OrderNum))
            {
                var childrenMenu = ResolveUserMenuTree(menus, menu.MenuID);

                MenuVM menusVM = new MenuVM
                {
                    MenuName = menu.MenuName,
                    MenuID = menu.MenuID,
                    OrderNum = menu.OrderNum,
                    PID = menu.PID,
                    MenuType = menu.MenuType,
                    Path = menu.Path,
                    Meta = menu.Meta,
                    ChildList = childrenMenu
                };

                userMenus.Add(menusVM);

            }

            return userMenus;
        }

    }

}
